<?php
/*
 *  This file is part of Urd.
 *
 *  Urd is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *  Urd is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program. See the file "COPYING". If it does not
 *  exist, see <http://www.gnu.org/licenses/>.
 *
 * $LastChangedDate: 2008-07-15 15:42:06 +0200 (Tue, 15 Jul 2008) $
 * $Rev: 1296 $
 * $Author: gavinspearhead $
 * $Id: checkauth.php 1296 2008-07-15 13:42:06Z gavinspearhead $
 */

// This is an include-only file:
if (!defined('ORIGINAL_PAGE')) die ('This file cannot be accessed directly.');
/*
 * the password is stored in the database hashed with a salt hence the database contains
 * username, salt, hash(salt, password, salt)   // where password is the plaintext salt
 * the cookie stores:
 * username, token, hash(token, hash(salt, password, salt), token)
 *
 * in case the pw is entered via a form field, it is checked against md5 of the entered password with database and the new pw is set
 * and it is checked against an unsalted pw, and the pw is reset.
 * For cookies/ sessions in this case the pw is considered wrong and a relogin is needed.
*/


$pathca = realpath(dirname(__FILE__));
session_name('URD_WEB'. md5($pathca)); // add the hashed path so we can have more than 1 session to different urds in one browser
@session_start();


$plain_password = $md5pass = '';
$__message = array();
if (isset($_POST['curr_language'])) {
    require_once("$pathca/web_functions.php");
    $languages = get_languages();
    $language = $_POST['curr_language'];
    if (in_array($language, array_keys($languages))) {
        if (isset($LN))
            unset($LN);
        load_language($language);
    }
} else if (!isset($LN) && !defined('SKIP_LANG')) {
    require_once("$pathca/web_functions.php");
    $language = get_config($db, 'default_language');
    load_language($language);
}

//$DONOT_SMARTIFY = 0;

function set_session_cookie($username, $password, $period, $token)
{
	assert(is_numeric($period) || $period == NULL); // NULL when it's 0...
	if ($period !== NULL) { // don't store the data in the cookie if the user won't like it (is gone after browser closes)
		// Set cookie:
		setcookie('urd_username', $username, $period);
		setcookie('urd_pass', $password, $period);
		setcookie('urd_period', "$period", $period);
		setcookie('urd_token', $token, $period);
		$_COOKIE['urd_username'] = $username;
		$_COOKIE['urd_pass'] = $password;
		$_COOKIE['urd_period'] = $period;
		$_COOKIE['urd_token'] = $token;
	}

	$_SESSION['urd_username'] = $username;
	$_SESSION['urd_pass'] = $password;
	$_SESSION['urd_period'] = $period;
	$_SESSION['urd_token'] = $token;
}


function hash_password($plain_password, $salt, $token)
{
    $salt_pw = $salt . $plain_password . $salt;
	$token_pw = $token . hash('sha256', $salt_pw) . $token;
    $password = hash('sha256', $token_pw );
    $md5pass = md5($token . md5($plain_password) . $token);
    return array($password, $md5pass);
}

$form_login = $log_ip = FALSE;
// Get all available users:
$res = $db->execute_query('SELECT count(*) AS cnt FROM users');
if ($res === FALSE || $res[0]['cnt'] == 0) {
	if (isset($__auth) && $__auth == 'silent') die();
	fatal_error($LN['error_nousers']);
}

// First, check for post (from login.php):
if (isset($_POST['username']) && isset($_POST['pass']) && isset($_POST['period']) && isset($_POST['token']) && $_POST['username'] != '' &&  $_POST['pass'] != '') {
    $username = $_POST['username'];
	$token = $_POST['token'];
	try {
		$salt = get_salt($db, $username);
		$plain_password = $_POST['pass'];
        list($password, $md5pass) = hash_password($plain_password, $salt, $token);
		$form_login = TRUE;
		if (isset($_POST['ipaddr']) &&  $_POST['ipaddr'] == 'on') 
			$log_ip = TRUE;

		// Set cookie:
		switch ($_POST['period']) {
		case 0: $period = NULL; break;
		case 1: $period = time() + 3600 * 24 * 7; break;
		case 2: $period = time() + 3600 * 24 * 30; break;
		case 3: $period = time() + 3600 * 24 * 365; break;
		case 4: $period = mktime(23,59,59,12,31,2037);break;
		default: $period = NULL; break;
		}

		// Set cookie variable for the current context
		//
		set_session_cookie($username, $password, $period, $token);
	} catch (exception $e) {
	}
}

// Examine cookie/session (old or brand new from above code):
if (isset($_SESSION['urd_username']) && isset($_SESSION['urd_pass']) && isset($_SESSION['urd_token'])) { // first try if we have a session
	$username = $_SESSION['urd_username'];
	$password = $_SESSION['urd_pass'];
	$token = $_SESSION['urd_token'];
} else if (isset($_COOKIE['urd_username']) && isset($_COOKIE['urd_pass']) && isset($_COOKIE['urd_token'])) { // if not try the cookie
	$username = $_COOKIE['urd_username'];
	$password = $_COOKIE['urd_pass'];
	$token = $_COOKIE['urd_token'];
}


function get_salt_(DatabaseConnection $db, $username)
{
	$sql = "\"salt\" FROM users WHERE \"name\" = '$username' AND \"active\" = '". USER_ACTIVE ."'";
	$res = $db->select_query($sql, 1);
	if ($res === FALSE) // no valid user found
		return FALSE;
	else 
		return $res[0]['salt'];
}


function check_password(DatabaseConnection $db,$username, $plain_password, $password, $md5pass, $token, &$res)
{
	$sql = "* FROM users WHERE \"name\" = '$username' AND \"active\" = '". USER_ACTIVE ."'";
	$res = $db->select_query($sql, 1);
	if ($res === FALSE) // no valid user found
		return FALSE;
	$salt_db = $res[0]['salt'];
	$password_db = $res[0]['pass'];
	if ($md5pass != '') { // check if the md5 stuff still matches... if not, we set the new pasword with salt
		if ($plain_password != '' && $md5pass == md5($token. $res[0]['pass'] . $token)) {
			set_password($db, $res[0]['ID'], $plain_password, FALSE);
			$sql = "* FROM users WHERE \"name\" = '$username' AND \"active\" = '". USER_ACTIVE ."'";
			$res = $db->select_query($sql, 1);
			if ($res === FALSE) // no valid user found
				return FALSE;
			$salt_db = $res[0]['salt'];
			$password_db = $res[0]['pass'];
			$password = hash('sha256', $token . hash('sha256', $salt_db. $plain_password. $salt_db) . $token);
			set_session_cookie($username, $password, $_SESSION['urd_period'], $token);
		}
	}
	if ($salt_db == '') {
		if($plain_password != '' && $password == hash('sha256', $token . $password_db . $token)) {// set the salt in de db
			set_password($db, $res[0]['ID'], $plain_password, FALSE);
			$sql = "* FROM users WHERE \"name\" = '$username' AND \"active\" = '". USER_ACTIVE ."'";
			$res = $db->select_query($sql, 1);
			if ($res === FALSE) // no valid user found
				return FALSE;
			$password_db = $res[0]['pass'];
			$salt_db = $res[0]['salt'];
			$password = hash('sha256', $token . hash('sha256', $salt_db. $plain_password. $salt_db) . $token);
			set_session_cookie($username, $password, $_SESSION['urd_period'], $token);
		} else 
			return FALSE;
	}

	$pw_hash = hash('sha256', $token . $password_db . $token);
	return $pw_hash == $password;
}


function get_hashed_password($db, $username)
{
	$sql = "\"salt\", \"pass\" FROM users WHERE \"name\" = '$username' AND \"active\" = '". USER_ACTIVE ."'";
	$res = $db->select_query($sql, 1);
	if ($res === FALSE) // no valid user found
		return FALSE;
	else 
		return $res[0]['password'];
}


// Found credentials? Check!
$valid = $isadmin = FALSE;
$ipaddr = $_SERVER['REMOTE_ADDR'];

if (isset($username, $password, $token)) {
	if (check_password($db, $username, $plain_password, $password, $md5pass, $token, $res)) {
		if ($form_login === TRUE) {
			$valid = TRUE;
			if ($log_ip !== TRUE) 
				$ipaddr = '';

			// if we log on from the form, we update the IP if requested
			set_login_ip($db, $ipaddr, $res[0]['ID']);
		}
		else if ($res[0]['ipaddr'] == '' ||  $res[0]['ipaddr'] == $ipaddr || $res[0]['ipaddr'] === NULL) {
			// if we use the cookie, we make sure the IP address is the same... otherwise user needs to login again
			$valid = TRUE;
		}
		$cur_time = time();
		if ($valid === TRUE){
			$userID = $res[0]['ID'];
			$isadmin = ($res[0]['isadmin'] == USER_ADMIN);
			$username = $res[0]['name'];
			
			if (isset($_SESSION['last_login']))
				$last_login = $_SESSION['last_login'];
			else {
				$_SESSION['last_login'] = $res[0]['last_login'];
				$last_login = $cur_time;
				if ($form_login === TRUE) 
					set_last_login($db, $last_login, $res[0]['ID']);
			}
			if (!isset($_SESSION['last_active']) || (($cur_time - $_SESSION['last_active'] ) > 60)) { // to cut down on excessive db updates
				set_last_active($db, $cur_time, $res[0]['ID']);
				$_SESSION['last_active'] = $cur_time;
			}
		}
	}
}


if (!isset($username) || $username == '' || $valid === FALSE) {
    try {
        $username = get_config($db, 'auto_login');
    } catch (exception $e) {
        $username = '';
    }
    if ($username != '' && $username != 'root') {
        $_SESSION['urd_token'] = '';
        $userID = get_userid($db, $username);
        if ($userID === FALSE || $userID == 0)
            $valid = FALSE;
        else {
            $_SESSION['urd_username'] = $username;
            $_SESSION['urd_pass'] = '';
            $_SESSION['urd_period'] = NULL;
            $valid = TRUE;
            $isadmin = is_admin($db, $username);
        }
    }
}


if ($valid !== TRUE) {
	// Invalid login
	// Write error message in case user tried to log in (this code is also accessed when user tries to access but not login yet):
	if (isset($username))
		write_log("Login failed for account '$username', IP address is " . $_SERVER['REMOTE_ADDR'],LOG_WARNING);

	// Remove cookie:
	@setcookie('urd_username', 0, time()-3600);
	@setcookie('urd_pass', 0, time()-3600);
	@setcookie('urd_period', 0, time()-3600);
	@setcookie('urd_cookie', 0, time()-3600);
	unset($_COOKIE['urd_username'], $_COOKIE['urd_pass'], $_COOKIE['urd_token'], $username, $isadmin, $userID);
	$_SESSION['urd_username'] = $_SESSION['urd_pass'] = $_SESSION['urd_period'] = $_SESSION['urd_token'] = '';
	// If ($__auth = 'silent') then just die without giving output (useful for some pages):
	if (isset($__auth) && $__auth == 'silent') die();

    // Otherwise, show login form
	if (isset($_POST['username']) && $_POST['username'] != '') 
		$__message[] = $LN['login_failed'] . '.';

	require $pathca.'/../html/login.php';
	die; // make sure we die
}

?>
